package com.sky.service.impl;

import com.sky.entity.Orders;
import com.sky.entity.OrdersStatistics;
import com.sky.entity.Sales;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.UserMapper;
import com.sky.service.DataStatisticsService;
import com.sky.service.WorkspaceService;
import com.sky.vo.*;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Service
public class DataStatisticsServiceImpl implements DataStatisticsService {

    @Resource(name = "orderMapper")
    OrderMapper orderMapper;
    @Resource(name = "userMapper")
    UserMapper userMapper;
    @Resource(name = "workspaceServiceImpl")
    WorkspaceService workspaceService;

    /**
     * 查询指定时间段内销量排名前10的商品信息。
     *
     * @param begin 查询开始时间
     * @param end   查询结束时间
     * @return SalesTop10ReportVO 销量前10报告的视图对象，包含商品名称列表和销量数字列表
     */
    @Override
    public SalesTop10ReportVO SalesTop10(LocalDate begin, LocalDate end) {
        // 将日期时间转换为LocalDateTime格式，分别设置为查询开始和结束时间
        LocalDateTime localDateTimeBegin = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime localDateTimeEnd = LocalDateTime.of(end, LocalTime.MAX);

        // 准备查询条件
        HashMap<Object, Object> map = new HashMap<Object, Object>();
        map.put("begin", localDateTimeBegin);
        map.put("end", localDateTimeEnd);
        map.put("status", Orders.COMPLETED); // 仅查询已完成的订单

        // 执行查询，获取销量前10的商品信息
        List<Sales> salesTop10List = orderMapper.selSalesTop(map);

        // 初始化名称和销量数组
        String[] nameArray = new String[10];
        Long[] numberArray = new Long[10];
        // 填充名称和销量数组
        if (salesTop10List.size() <= 10) {
            for (int i = 0; i < salesTop10List.size(); i++) {
                nameArray[i] = salesTop10List.get(i).getName();
                numberArray[i] = salesTop10List.get(i).getSalesVolume();
            }
        } else {
            for (int i = 0; i < numberArray.length; i++) {
                nameArray[i] = salesTop10List.get(i).getName();
                numberArray[i] = salesTop10List.get(i).getSalesVolume();
            }
        }

        // 构建并返回销量前10报告的视图对象
        return SalesTop10ReportVO.builder()
                .nameList(StringUtils.join(nameArray, ","))
                .numberList(StringUtils.join(numberArray, ","))
                .build();
    }


    /**
     * 营业额统计接口。该方法用于根据指定的开始日期和结束日期，统计这段时间内的营业额情况。
     *
     * @param begin 统计的开始日期，不可为null。
     * @param end   统计的结束日期，不可为null。结束日期不包含在统计范围内。
     * @return TurnoverReportVO 转换率报告值对象，包含日期列表和对应的营业额列表。
     */
    @Override
    public TurnoverReportVO turnoverStatistics(LocalDate begin, LocalDate end) {
        // 初始化日期和营业额列表
        List<LocalDate> localDateArrayList = new ArrayList<>();
        ArrayList<Double> doubleArrayList = new ArrayList<>();
        // 处理时间段内的每一天
        while (!begin.equals(end.plusDays(1))) {
            localDateArrayList.add(begin);
            begin = begin.plusDays(1);
        }
        // 遍历日期列表，为每一天计算营业额
        for (LocalDate localDate : localDateArrayList) {
            LocalDateTime localDateTimeBegin = LocalDateTime.of(localDate, LocalTime.MIN);
            LocalDateTime localDateTimeEnd = LocalDateTime.of(localDate, LocalTime.MAX);
            HashMap<Object, Object> map = new HashMap<>();
            map.put("localDateTimeBegin", localDateTimeBegin);
            map.put("localDateTimeEnd", localDateTimeEnd);
            map.put("status", Orders.COMPLETED);
            // 查询并累加当天的营业额
            Double turnover = orderMapper.turnoverStatistics(map);
            doubleArrayList.add(turnover);
        }

        // 构建并返回营业额报告
        return TurnoverReportVO.builder()
                .dateList(StringUtils.join(localDateArrayList, ","))
                .turnoverList(StringUtils.join(doubleArrayList, ","))
                .build();
    }

    /**
     * 用户统计接口
     *
     * @param begin 统计的开始日期
     * @param end   统计的结束日期
     * @return UserReportVO 包含用户统计数据的视图对象，其中包括日期列表、新用户数量列表和总用户数量列表。
     */
    @Override
    public UserReportVO userStatistics(LocalDate begin, LocalDate end) {
        // 根据创建时间获取开始日期以前的用户数量
        Long number = userMapper.userNumberByCreateTime(LocalDateTime.of(begin, LocalTime.MIN));

        // 初始化日期范围集合
        List<LocalDate> localDateArrayList = new ArrayList<>();
        // 逐日添加到日期范围集合中，直到结束日期
        while (!begin.equals(end.plusDays(1))) {
            localDateArrayList.add(begin);
            begin = begin.plusDays(1);
        }

        // 初始化新用户数量和总用户数量集合
        List<Long> userArrayList = new ArrayList<>();
        List<Long> totalUserList = new ArrayList<>();
        // 遍历日期范围，统计每一天的新用户数量和总用户数量
        for (LocalDate date : localDateArrayList) {
            HashMap<Object, Object> map = new HashMap<Object, Object>();
            // 设置统计时间范围的开始和结束时间
            LocalDateTime beginDate = LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime endDate = LocalDateTime.of(date, LocalTime.MAX);
            map.put("begin", beginDate);
            map.put("end", endDate);
            // 获取指定时间范围内的新用户数量
            Long userStatistics = userMapper.userStatistics(map);
            userArrayList.add(userStatistics);
            number += userStatistics;
            totalUserList.add(number);
        }

        // 构建并返回用户统计报告
        return UserReportVO.builder()
                .dateList(StringUtils.join(localDateArrayList, ","))
                .newUserList(StringUtils.join(userArrayList, ","))
                .totalUserList(StringUtils.join(totalUserList, ","))
                .build();
    }

    /**
     * 订单统计接口
     *
     * @param begin 统计的开始日期
     * @param end   统计的结束日期
     * @return OrderReportVO 返回订单统计报告的视图对象，包含日期列表、每日订单数列表、每日有效订单数列表、
     * 总订单数、有效订单数和订单完成率。
     */
    @Override
    public OrderReportVO ordersStatistics(LocalDate begin, LocalDate end) {

        // 初始化日期范围集合，用于存储从开始日期到结束日期的所有日期
        List<LocalDate> localDateArrayList = new ArrayList<>();
        while (!begin.equals(end.plusDays(1))) {
            localDateArrayList.add(begin);
            begin = begin.plusDays(1);
        }

        // 统计每日订单数和有效订单数
        List<Integer> dayOrderArrayList = new ArrayList<>();
        List<Integer> daySucceedOrderArrayList = new ArrayList<>();
        for (LocalDate date : localDateArrayList) {
            HashMap<Object, Object> map = new HashMap<Object, Object>();
            LocalDateTime beginDate = LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime endDate = LocalDateTime.of(date, LocalTime.MAX);
            map.put("begin", beginDate);
            map.put("end", endDate);
            OrdersStatistics ordersStatistics = orderMapper.ordersStatistics(map);
            dayOrderArrayList.add(ordersStatistics.getOrderQuantity());
            daySucceedOrderArrayList.add(ordersStatistics.getSucceedOrderQuantity());
        }

        // 计算总订单数和有效订单数，用于计算订单完成率
        HashMap<Object, Object> map = new HashMap<Object, Object>();
        LocalDateTime beginDate = LocalDateTime.of(localDateArrayList.get(0), LocalTime.MIN);
        LocalDateTime endDate = LocalDateTime.of(localDateArrayList.get(localDateArrayList.size() - 1), LocalTime.MAX);
        map.put("begin", beginDate);
        map.put("end", endDate);
        OrdersStatistics ordersStatistics = orderMapper.ordersStatistics(map);
        Integer totalOrderCount = ordersStatistics.getOrderQuantity();
        Integer validOrderCount = ordersStatistics.getSucceedOrderQuantity();
        Double orderCompletionRate = (double) validOrderCount / (double) totalOrderCount;

        // 构建并返回订单统计报告的视图对象
        return OrderReportVO.builder()
                .dateList(StringUtils.join(localDateArrayList, ","))
                .orderCountList(StringUtils.join(dayOrderArrayList, ","))
                .validOrderCountList(StringUtils.join(daySucceedOrderArrayList, ","))
                .totalOrderCount(totalOrderCount)
                .validOrderCount(validOrderCount)
                .orderCompletionRate(orderCompletionRate)
                .build();
    }

    //导出Excel报表
    @Override
    public void exportBusinessData(HttpServletResponse response) {
        //准备数据
        LocalDate begin = LocalDate.now().minusDays(30);
        LocalDate end = LocalDate.now().minusDays(1);
        BusinessDataVO businessData = workspaceService.getBusinessData(LocalDateTime.of(begin, LocalTime.MIN), LocalDateTime.of(end, LocalTime.MAX));
        List<BusinessDataVO> businessDataVOList = new ArrayList<>();
        LocalDate date = begin;
        for (int i = 0; i < 30; i++) {
            businessDataVOList.add(workspaceService.getBusinessData(LocalDateTime.of(date, LocalTime.MIN), LocalDateTime.of(date, LocalTime.MAX)));
            date = date.plusDays(1);
        }

        //插入数据
        InputStream stream = this.getClass().getClassLoader().getResourceAsStream("template/运营数据报表模板.xlsx");
        try {
            XSSFWorkbook excel = new XSSFWorkbook(stream);
            XSSFSheet sheet = excel.getSheetAt(0);
            XSSFRow row = sheet.getRow(1);
            row.getCell(1).setCellValue("时间：" + begin + "至" + end);
            row = sheet.getRow(3);
            row.getCell(2).setCellValue(businessData.getTurnover());
            row.getCell(4).setCellValue(businessData.getOrderCompletionRate());
            row.getCell(6).setCellValue(businessData.getNewUsers());
            row = sheet.getRow(4);
            row.getCell(2).setCellValue(businessData.getValidOrderCount());
            row.getCell(4).setCellValue(businessData.getUnitPrice());
            for (int i = 7; i < 7 + 30; i++) {
                row = sheet.getRow(i);
                BusinessDataVO businessDataVO = businessDataVOList.get(i - 7);
                row.getCell(1).setCellValue(begin.toString());
                row.getCell(2).setCellValue(businessDataVO.getTurnover());
                row.getCell(3).setCellValue(businessDataVO.getValidOrderCount()==null?0:businessDataVO.getValidOrderCount());
                row.getCell(4).setCellValue(businessDataVO.getOrderCompletionRate());
                row.getCell(5).setCellValue(businessDataVO.getUnitPrice());
                row.getCell(6).setCellValue(businessDataVO.getNewUsers());
                begin = begin.plusDays(1);
            }
            //下载报表
            ServletOutputStream outputStream = response.getOutputStream();
            excel.write(outputStream);
            outputStream.close();
            excel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

}
